package org.leon.framework;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.leon.HttpServlet;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLStreamHandler;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Context {

    private final String WEB_INF = "WEB-INF";
    private final String WEB_CONFIG_FILE_NAME = "web.xml";

    // servlet 请求地址与 servlet 实例映射
    private Map<String, Wrapper> wrapperMap = new HashMap<>();

    private String contextPath;

    private String appBase;

    public Context(String contextPath, String appBase) {
        this.contextPath = contextPath;
        this.appBase = appBase;
    }

    // 初始化
    public void init() throws Exception {
        File file = new File(this.appBase + File.separator + this.contextPath);
        String[] list = file.list();
        for (String fn : list) {
            if (fn.equals(WEB_INF)) {
                String webXml = this.appBase + File.separator + this.contextPath + File.separator + WEB_INF + File.separator + WEB_CONFIG_FILE_NAME;
                File configFile = new File(webXml);

                if (!configFile.exists()) {
                    throw new Exception("项目不存在 web 配置文件");
                }

                // 解析配置文件
                parseWebConfigFile(configFile);
            }
        }
    }

    // 解析项目的 web.xml 文件
    private void parseWebConfigFile(File configFile) throws FileNotFoundException {
        InputStream inputStream = new FileInputStream(configFile);

        SAXReader reader = new SAXReader();

        try {
            Document document = reader.read(inputStream);
            Element rootElement = document.getRootElement();

            List<Element> nodes = rootElement.selectNodes("//servlet");
            for (int i = 0; i <nodes.size() ; i++) {
                Element element = nodes.get(i);
                Element servletNameEle = (Element)element.selectSingleNode("servlet-name");
                String servletName = servletNameEle.getStringValue();

                Element servletClassEle = (Element) element.selectSingleNode("servlet-class");
                String servletCls = servletClassEle.getStringValue();

                // 使用 xpath 表达式找到 servletName 对应的 servlet-mapping 元素，然后从中取得 url-pattern 的值
                Element servletMappingEle = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
                String urlPattern = servletMappingEle.selectSingleNode("url-pattern").getStringValue();


                Wrapper wrapper = buildWrapper(servletCls);
                wrapperMap.put(urlPattern, wrapper);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    // 使用 URL 类加载器加载指定目录的 class 文件
    private Wrapper buildWrapper(String servletClz) throws Exception {
        String path = this.appBase + File.separator + this.contextPath + File.separator;
        File classpath = new File(path);
        URL[] urls = new URL[1];

        String repository =(new URL("file", null, classpath.getCanonicalPath() + File.separator)).toString() ;
        URLStreamHandler streamHandler = null;
        urls[0] = new URL(null, repository, streamHandler);
        URLClassLoader loader = new URLClassLoader(urls);

        // this class should be loaded from your directory
        Class< ? > clazz = loader.loadClass( servletClz);

        HttpServlet instance = (HttpServlet) clazz.getDeclaredConstructor().newInstance();

        Wrapper wrapper = new Wrapper();
        wrapper.setInstance(instance);

        return wrapper;
    }

    public Wrapper getWrapper(String uri) {
        return wrapperMap.get(uri);
    }
}
